#pragma once
#include "matrix.h"
inline
matrix4f lookat(vertex eye, vertex center, vertex up) {
    vertex f = (center - eye).normalize();
    vertex s = f.cross(up).normalize();
    vertex u = s.cross(f);

    matrix4f m {
        s[0], s[1], s[2], 0,
        u[0], u[1], u[2], 0,
        -f[0], -f[1], -f[2], 0,
        0, 0, 0, 1
    };

    return m;
}

inline
matrix4f perspective(float fovy, float aspect, float near, float far) {
    float f = 1.0 / tan((M_PI / fovy) / 2.0);
    matrix4f m {
        f / aspect, 0, 0, 0,
        0, f, 0, 0, 
        0, 0, (far + near) / (near - far), (2 * far + near) / (near - far),
        0, 0, -1, 0
    };
    return m;
}

inline
matrix4f ortho(float left, float right, float bottom, float top, float near, float far) {
    float tx = (right + left) / (right - left);
    float ty = (top + bottom) / (top - bottom);
    float tz = (far + near) / (far - near);
    matrix4f m {
        2.0f / (right - left), 0, 0, tx,
        0, 2.0f / (top - bottom), 0, ty,
        0, 0, -2 / (far - near), tz,
        0, 0, 0, 1
    };
    return m;
}

inline
matrix4f translate(const vec3f& v) {
    matrix4f m {
        1, 0, 0, v[0],
        0, 1, 0, v[1],
        0, 0, 1, v[2],
        0, 0, 0, 1
    };
    return m;
}

inline
matrix4f rtranslate(const vec3f& v) {
    return translate(v * -1.0f);
}

inline
matrix4f scale(const vec3f& v) {
    matrix4f m {
        v[0], 0, 0, 0,
        0, v[1], 0, 0,
        0, 0, v[2], 0,
        0, 0, 0, 1
    };
    return m;
}
